import logging
import os
import os.path
import tempfile
from typing import Optional, Tuple

import imagehash
import pendulum
import requests
import uuid
from PIL import Image
from starlette.endpoints import HTTPEndpoint
from starlette.responses import JSONResponse

import config
from dao import DaoWorkRecord, DaoSuperviseRecord
from database import Session
from model.ModPhotoIndex import PhotoIndex
from model.ModWorkRecord import WorkRecord
from redis_connection import redis_conn as redis
from utils import Switch


class WorkRecordInsert(HTTPEndpoint):

    def __init__(self, scope):
        super().__init__(scope)
        self._logger = logging.getLogger(type(self).__name__)

    async def post(self, request):
        session = Session()
        try:
            dict_work = await request.json()
            photo_fingerprint = ""
            if len(dict_work["photo_fingerprint"]) > 0:
                photo = self._save_picture(dict_work["photo_fingerprint"])
                if photo is None:
                    raise OSError()
                photo_fingerprint, photo_path = photo
                self._logger.debug(f"Photo: {photo_fingerprint}")
                new_photo = PhotoIndex(photo_fingerprint=photo_fingerprint,
                                       storage_path=config.UPLOAD_PATH,
                                       access_path=photo_path)
                session.add(new_photo)

            work = WorkRecord()
            message_str = ""
            if len(dict_work["bureauid"]) > 0:
                work.bureauid = dict_work.get("bureauid")
            else:
                message_str = "县局名称、"

            if len(dict_work["stationid"]) > 0:
                work.stationid = dict_work.get("stationid")
            else:
                message_str = message_str + "供电所名称、"
            work.openid = dict_work.get("openid")
            work.opentime = pendulum.now("Asia/Shanghai")
            self._logger.debug(f"[TIME_DEBUG] {work.opentime}")
            if len(dict_work["flag"]) > 0:
                work.flag = dict_work.get("flag")
            else:
                message_str = message_str + "专公变、"

            if len(dict_work["meter_barcode"]) > 0:
                work.meter_barcode = dict_work.get("meter_barcode")
            else:
                message_str = message_str + "电能表条码、"
            if len(dict_work["problemid"]) > 0:
                work.problemid = dict_work.get("problemid")
            else:
                message_str = message_str + "问题类型、"
            work.longitude_latitude = dict_work.get("longitude_latitude")
            work.photo_fingerprint = photo_fingerprint
            if len(dict_work["resolventid"]) > 0:
                work.resolventid = dict_work.get("resolventid")
            else:
                message_str = message_str + "解决方法"
            work.equ_venderid = dict_work.get("equ_venderid")
            work.remark = dict_work.get("remark")
            work.serial_number = uuid.uuid1()
            work.flag_result = "0"
            if len(message_str) > 0:
                last_str = message_str[-1]
                if last_str == "、":
                    message_str = message_str[:-1]
                message_str = "请确认：" + message_str + "等信息是否填写完整！"
                return JSONResponse({"result": "2", "message_str": message_str})
            DaoWorkRecord.insert_work_record(session, work)
            #name_operation = request.user.display_name
            #去掉运维协助处理
            #if dict_work.get("flag_supervise") == "1":
             #  DaoSuperviseRecord.update_serial_number_operation(session, dict_work["bureauid"],
              #                                                    str(work.serial_number), work.meter_barcode,
                  #                                                work.openid, work.opentime, name_operation)
            session.commit()
            return JSONResponse({"result": "1"})
        except Exception as e:
            self._logger.info(e)
            session.rollback()
            return JSONResponse({"result": "0"})
        finally:
            session.close()

    def _save_picture(self, media_id: str) -> Optional[Tuple[str, str]]:
        """
        用微信素材的Media ID来下载指定素材图片，并计算图片指纹。
        注意：本下载方法仅支持JPEG和PNG两种文件格式，由微信返回的响应头属性Content-Type确定。
        :param media_id: 素材Media ID
        :return: 返回元组(图片指纹，图片保存路径)，如果出现下载错误等，则返回None。
        """
        try:
            token = redis.hget(config.ENT_ACCESS_TOKEN, "token")
            media_file_request = requests.get(f"https://qyapi.weixin.qq.com/cgi-bin/media/get",
                                              params={
                                                  "access_token": token,
                                                  "media_id": media_id
                                              },
                                              stream=True)
            media_file_request.raise_for_status()

            # 判断上传的文件类型
            content_type = media_file_request.headers["Content-Type"]
            file_type = ""
            for case in Switch(content_type.lower()):
                if case("image/jpeg"):
                    file_type = "jpg"
                    break
                if case("image/png"):
                    file_type = "png"
                    break
                if case():
                    self._logger.debug(f"响应头中的Content-Type为{content_type.lower()}")
                    raise ValueError("Unsupported content type")

            # 转置到临时文件计算图片指纹，之后再转置到uploads目录
            with tempfile.TemporaryFile() as tmp:
                for chunk in media_file_request.iter_content(chunk_size=512):
                    if chunk:
                        tmp.write(chunk)
                image_fingerprint = imagehash.phash(Image.open(tmp))
                image_file_name = f"{image_fingerprint}.{file_type}"
                upload_file_name = f"{config.UPLOAD_PATH}/{image_file_name}"
                if not os.path.exists(f"{config.UPLOAD_PATH}"):
                    os.makedirs(f"{config.UPLOAD_PATH}")
                with open(upload_file_name, "wb") as upload:
                    tmp.seek(0)
                    while True:
                        content = tmp.read(512)
                        if not content:
                            break
                        upload.write(content)

            return str(image_fingerprint), image_file_name
        except OSError:
            self._logger.info("文件转置失败，将目录设为了移动目标。")
            return None
        except ValueError:
            self._logger.info("微信素材解析失败，因为Content-Type无法识别。")
            return None
        except requests.HTTPError:
            self._logger.info("微信素材下载请求失败。")
            return None
